package com.kxmall.web.controller.huishou.listeners;

import cn.hutool.core.collection.CollUtil;
import cn.hutool.core.date.DateUtil;
import cn.hutool.core.util.IdUtil;
import cn.hutool.core.util.StrUtil;
import cn.hutool.extra.spring.SpringUtil;
import com.alibaba.excel.context.AnalysisContext;
import com.alibaba.excel.event.AnalysisEventListener;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.kxmall.categorize.domain.HsWasteCategorize;
import com.kxmall.categorize.mapper.HsWasteCategorizeMapper;
import com.kxmall.common.excel.ExcelListener;
import com.kxmall.common.excel.ExcelResult;
import com.kxmall.common.exception.ServiceException;
import com.kxmall.common.helper.LoginHelper;
import com.kxmall.huishou.domain.HsSettlementOrder;
import com.kxmall.huishou.domain.HsUserWaste;
import com.kxmall.huishou.domain.vo.HsSettlementOrderExport;
import com.kxmall.huishou.mapper.HsSettlementOrderMapper;
import com.kxmall.huishou.mapper.HsUserWasteMapper;
import com.kxmall.rider.domain.KxRider;
import com.kxmall.rider.mapper.KxRiderMapper;
import com.kxmall.user.domain.KxUser;
import com.kxmall.user.mapper.KxUserMapper;
import lombok.extern.slf4j.Slf4j;

import java.math.BigDecimal;
import java.util.*;
import java.util.stream.Collectors;

/**
 * 系统用户自定义导入
 *
 * @author kxmall
 */
@Slf4j
public class SettlementOrderImportListener extends AnalysisEventListener<HsSettlementOrderExport> implements ExcelListener<HsSettlementOrderExport> {

    private final String operName;
    /**
     * 批量数据限制
     */
    private final static Integer BATCH_COUNT = 1000;
    /**
     * 已读取的订单映射关系
     */
    private HashMap<String, List<HsSettlementOrderExport>> readMap = new HashMap<>();

    /**
     * 骑手电话集合
     */
    private Set<String> riderPhoneList = new HashSet<>();
    /**
     * 用户电话集合
     */
    private Set<String> userPhoneList = new HashSet<>();
    /**
     * 分类名称集合
     */
    private Set<String> categorizeNameList = new HashSet<>();

    private int successNum = 0;
    private int failureNum = 0;
    private final StringBuilder successMsg = new StringBuilder();
    private final StringBuilder failureMsg = new StringBuilder();

    private KxRiderMapper kxRiderMapper;
    private KxUserMapper kxUserMapper;
    private HsWasteCategorizeMapper hsWasteCategorizeMapper;
    private HsSettlementOrderMapper hsSettlementOrderMapper;
    private HsUserWasteMapper hsUserWasteMapper;

    public SettlementOrderImportListener() {
        this.operName = LoginHelper.getUsername();
        this.kxRiderMapper = SpringUtil.getBean(KxRiderMapper.class);
        this.kxUserMapper = SpringUtil.getBean(KxUserMapper.class);
        this.hsWasteCategorizeMapper = SpringUtil.getBean(HsWasteCategorizeMapper.class);
        this.hsSettlementOrderMapper = SpringUtil.getBean(HsSettlementOrderMapper.class);
        this.hsUserWasteMapper = SpringUtil.getBean(HsUserWasteMapper.class);
    }

    @Override
    public void invoke(HsSettlementOrderExport orderVo, AnalysisContext context) {
        if (StrUtil.isBlank(orderVo.getRiderPhone())){
            throw new ServiceException("派送员手机号必填");
        }
        if (StrUtil.isBlank(orderVo.getUserPhone())){
            throw new ServiceException("下单用户手机号必填");
        }
        if (orderVo.getCreateTime() == null) {
            throw new ServiceException("下单时间必填");
        }
        if (StrUtil.isBlank(orderVo.getCategorizeName())) {
            throw new ServiceException("分类必填");
        }
        String orderNo = "HSJS"+ DateUtil.format(orderVo.getCreateTime(), "yyyyMMddHHmmss");
        List<HsSettlementOrderExport> orDefault = readMap.getOrDefault(orderNo, new ArrayList<>());
        orderVo.setOrderNo(orderNo);
        orDefault.add(orderVo);
        riderPhoneList.add(orderVo.getRiderPhone());
        userPhoneList.add(orderVo.getUserPhone());
        categorizeNameList.add(orderVo.getCategorizeName());
        readMap.put(orderNo, orDefault);
    }

    @Override
    public void doAfterAllAnalysed(AnalysisContext context) {
        List<HsSettlementOrder> orderList = new ArrayList<>();
        HsSettlementOrder orderItem = null;

        List<HsUserWaste> wasteList = new ArrayList<>();
        HsUserWaste wasteItem = null;

        LambdaQueryWrapper<KxRider> kxRiderLambdaQueryWrapper = new LambdaQueryWrapper<>();
        List<String> riderList = this.riderPhoneList.stream().distinct().collect(Collectors.toList());
        kxRiderLambdaQueryWrapper.in(KxRider::getPhone, riderList);
        List<KxRider> kxRiders = kxRiderMapper.selectList(kxRiderLambdaQueryWrapper);
        Map<String, KxRider> riderMap = new HashMap<>();
        if (CollUtil.isNotEmpty(kxRiders)) {
            riderMap = kxRiders.stream().collect(Collectors.toMap(KxRider::getPhone, item -> item));
        }

        Map<String, KxUser> userMap = new HashMap<>();
        List<String> userList = this.userPhoneList.stream().distinct().collect(Collectors.toList());
        LambdaQueryWrapper<KxUser> kxUserLambdaQueryWrapper = new LambdaQueryWrapper<>();
        kxUserLambdaQueryWrapper.in(KxUser::getPhone, userList);
        List<KxUser> kxUsers = kxUserMapper.selectList(kxUserLambdaQueryWrapper);
        if (CollUtil.isNotEmpty(kxUsers)) {
            userMap =  kxUsers.stream().collect(Collectors.toMap(KxUser::getPhone, item -> item));
        }

        LambdaQueryWrapper<HsWasteCategorize> hsWasteCategorizeLambdaQueryWrapper = new LambdaQueryWrapper<>();
        hsWasteCategorizeLambdaQueryWrapper.in(HsWasteCategorize::getName, categorizeNameList);
        List<HsWasteCategorize> hsWasteCategorizes = hsWasteCategorizeMapper.selectList(hsWasteCategorizeLambdaQueryWrapper);
        Map<String, HsWasteCategorize> categorizeMap = new HashMap<>();
        if (CollUtil.isNotEmpty(hsWasteCategorizes)) {
            categorizeMap = hsWasteCategorizes.stream().collect(Collectors.toMap(HsWasteCategorize::getName, item -> item));
        }

        for (Map.Entry<String, List<HsSettlementOrderExport>> entry : readMap.entrySet()) {
            String key = entry.getKey();
            List<HsSettlementOrderExport> value = entry.getValue();
            orderItem = new HsSettlementOrder();

            genOrderItem(value, riderMap,userMap, orderItem, key, orderList);

            for (HsSettlementOrderExport settlementOrderExport : value) {
                wasteItem = new HsUserWaste();

                getnWasteItem(settlementOrderExport, categorizeMap, wasteItem, orderItem, wasteList);
            }
        }

        int pageIndex = 0;
        int pages = orderList.size() / BATCH_COUNT + orderList.size() % BATCH_COUNT == 0 ? 0 : 1;
        do {
            int fromIndex = pageIndex * BATCH_COUNT;
            int toIndex = (pageIndex + 1) * BATCH_COUNT;
            if (toIndex >= orderList.size()) {
                toIndex = orderList.size();
            }
            List<HsSettlementOrder> pagesOrder = orderList.subList(fromIndex, toIndex);
            pageIndex++;

            hsSettlementOrderMapper.insertBatch(pagesOrder);
        } while (pageIndex < pages);

        pageIndex = 0;
        pages = wasteList.size() / BATCH_COUNT + wasteList.size() % BATCH_COUNT == 0 ? 0 : 1;
        do {
            int fromIndex = pageIndex * BATCH_COUNT;
            int toIndex = (pageIndex + 1) * BATCH_COUNT;
            if (toIndex >= wasteList.size()) {
                toIndex = wasteList.size();
            }
            List<HsUserWaste> pagesWaste = wasteList.subList(fromIndex, toIndex);
            pageIndex++;

            hsUserWasteMapper.insertBatch(pagesWaste);
        } while (pageIndex < pages);

        successNum = wasteList.size();
    }

    /**
     * 获取回收物的信息
     *
     * @param settlementOrderExport
     * @param categorizeMap
     * @param wasteItem
     * @param orderItem
     * @param wasteList
     */
    private static void getnWasteItem(HsSettlementOrderExport settlementOrderExport, Map<String, HsWasteCategorize> categorizeMap, HsUserWaste wasteItem, HsSettlementOrder orderItem, List<HsUserWaste> wasteList) {
        String categorizeName = settlementOrderExport.getCategorizeName();
        if (StrUtil.isBlank(categorizeName)) {
            throw new ServiceException("分类数据异常");
        }
        HsWasteCategorize hsWasteCategorize = categorizeMap.get(categorizeName);
        if (hsWasteCategorize == null) {
            throw new ServiceException("分类信息异常");
        }

        wasteItem.setOrderId(orderItem.getId());
        wasteItem.setOrderType(1L);
        wasteItem.setCategorizeId(hsWasteCategorize.getId());
        wasteItem.setCategorizeName(categorizeName);
        wasteItem.setWeight(settlementOrderExport.getWeight());
        wasteItem.setAmount(settlementOrderExport.getAmount());
        wasteItem.setPrice(settlementOrderExport.getPrice());
        wasteItem.setCreateTime(settlementOrderExport.getCreateTime());
        wasteItem.setUpdateTime(settlementOrderExport.getCreateTime());
        wasteList.add(wasteItem);
    }

    /**
     * 获取订单基础信息元素对象
     *
     * @param value
     * @param riderMap
     * @param orderItem
     * @param key
     * @param orderList
     */
    private static void genOrderItem(List<HsSettlementOrderExport> value, Map<String, KxRider> riderMap,Map<String, KxUser> userMap, HsSettlementOrder orderItem, String key, List<HsSettlementOrder> orderList) {
        BigDecimal totalWeight = value.stream()
                .map(HsSettlementOrderExport::getWeight)
                .filter(Objects::nonNull)
                .reduce(BigDecimal::add)
                .orElse(BigDecimal.ZERO);

        BigDecimal totalAmount = value.stream()
                .map(HsSettlementOrderExport::getAmount)
                .filter(Objects::nonNull)
                .reduce(BigDecimal::add)
                .orElse(BigDecimal.ZERO);

        if (CollUtil.isEmpty(value)) {
            throw new ServiceException("订单相关信息异常");
        }
        HsSettlementOrderExport hsSettlementOrderExport = value.get(0);
        String riderPhone = hsSettlementOrderExport.getRiderPhone();
        if (StrUtil.isBlank(riderPhone)) {
            throw new ServiceException("骑手信息异常");
        }
        KxRider kxRider = riderMap.get(riderPhone);
        if (kxRider == null) {
            throw new ServiceException("骑手信息异常");
        }

        String userPhone = hsSettlementOrderExport.getUserPhone();
        if (StrUtil.isBlank(userPhone)) {
            throw new ServiceException("下单用户信息异常");
        }
        KxUser kxUser = userMap.get(userPhone);
        Long uid = 0L;
        if (kxUser == null) {
//            throw new ServiceException("下单用户信息异常");
//            Long uid =  0l;
        }else{
             uid =  kxUser.getUid();
        }

        orderItem.setOrderNo(key);
        orderItem.setWeightTal(totalWeight);
        orderItem.setAmountTal(totalAmount);
        orderItem.setRiderId(kxRider.getId());
        orderItem.setUserId(uid);
        orderItem.setImgUrl(null);
        orderItem.setPayType(4);
        orderItem.setStatus(4L);
        orderItem.setLinkType(1);
        orderItem.setDataFrom(1);
        orderItem.setId(IdUtil.getSnowflakeNextId());
        orderItem.setCreateTime(hsSettlementOrderExport.getCreateTime());
        orderItem.setUpdateTime(hsSettlementOrderExport.getCreateTime());
        orderList.add(orderItem);
    }

    @Override
    public ExcelResult<HsSettlementOrderExport> getExcelResult() {
        return new ExcelResult<HsSettlementOrderExport>() {

            @Override
            public String getAnalysis() {
                if (failureNum > 0) {
                    failureMsg.insert(0, "很抱歉，导入失败！共 " + failureNum + " 条数据格式不正确，错误如下：");
                    throw new ServiceException(failureMsg.toString());
                } else {
                    successMsg.insert(0, "恭喜您，数据已全部导入成功！共 " + successNum + " 条，数据如下：");
                }
                return successMsg.toString();
            }

            @Override
            public List<HsSettlementOrderExport> getList() {
                return null;
            }

            @Override
            public List<String> getErrorList() {
                return null;
            }
        };
    }
}
